package com.example.gobang.api;

import com.example.gobang.game.*;
import com.example.gobang.model.User;
import com.example.gobang.model.UserMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

@Component
public class GameAPI extends TextWebSocketHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomManager roomManager;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private UserMapper userMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
       System.out.println("afterConnectionEstablished");
        GameReadyResponse resp = new GameReadyResponse();

        User user = (User) session.getAttributes().get("user");
        System.out.println("当前用户的session:"+user);
        if(user == null) {
            resp.setOk(false);
            resp.setReason("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;

        }

        Room room = roomManager.getRoomByUserId(user.getUserId());
        if(room == null) {
            resp.setOk(false);
            resp.setReason("用户尚未匹配到!");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;
        }


        if(onlineUserManager.getFromGameHall(user.getUserId()) != null
        || onlineUserManager.getFromGameRoom(user.getUserId()) != null) {
            resp.setOk(true);
            resp.setReason("禁止多开游戏页面");
            resp.setMessage("repeatConnection");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;

        }

        // 当前用户加入了游戏房间,那么大厅应该就需要删掉这个用户
        //onlineUserManager.exitGameHall(user.getUserId());
        //将当前用户加入游戏房间
        onlineUserManager.enterGameRoom(user.getUserId(), session);

        synchronized (room) {
            if(room.getUser1() == null) {
                room.setUser1(user);
                room.setWhiteUser(user.getUserId());
                System.out.println("玩家1" + user.getUsername() + "已经准备就绪!");
                return;
            }
            if(room.getUser2() == null) {
                room.setUser2(user);
                System.out.println("玩家2" +user.getUsername() + "已经准备就绪!");
                noticeGameReady(room,room.getUser1(),room.getUser2());
                noticeGameReady(room,room.getUser2(),room.getUser1());
                return;
            }
        }


        resp.setOk(false);
        resp.setReason("当前房间已满, 您不能加入房间");
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));



    }

    private void noticeGameReady(Room room, User thisUser, User thatUser) throws IOException {
        System.out.println("noticeGameReady");
        GameReadyResponse resp = new GameReadyResponse();
        resp.setMessage("gameReady");
        resp.setOk(true);
        resp.setReason("");
        resp.setRoomId(room.getRoomId());
        resp.setThisUserId(thisUser.getUserId());
        resp.setThatUserId(thatUser.getUserId());
        resp.setWhiteUser(room.getWhiteUser());
        // 把当前的响应数据传回给玩家.
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(thisUser.getUserId());

        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
   }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("收到落子请求了");
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            System.out.println("[handleTextMessage] 当前玩家尚未登录");
            return;
        }

        Room room = roomManager.getRoomByUserId(user.getUserId());

        room.putChess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("handleTransportError");
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            return;
        }

        WebSocketSession exitSession = onlineUserManager.getFromGameRoom(user.getUserId());
        if(session == exitSession) {
            onlineUserManager.exitGameHall(user.getUserId());
        }
        System.out.println("当前用户" + user.getUsername() + "游戏房间连接异常!");

        noticeThatUserWin(user);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("afterConnectionClosed-gameapi");
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            return;
        }

        WebSocketSession exitSession = onlineUserManager.getFromGameRoom(user.getUserId());
        if(session == exitSession) {
            onlineUserManager.exitGameHall(user.getUserId());
        }
        System.out.println("当前用户" + user.getUsername() + "离开游戏房间!");

        noticeThatUserWin(user);

    }

    private void noticeThatUserWin(User user) throws IOException {
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if(room == null) {

            System.out.println("当前房间已经释放,无需通知对手!");
            return;
        }

        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();

        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(thatUser.getUserId());
        if(webSocketSession == null) {
            System.out.println("对手也掉线了,无需通知!");
            return;
        }
        GameResponse resp = new GameResponse();
        resp.setMessage("putChess");
        resp.setUserId(thatUser.getUserId());
        resp.setWinner(thatUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

        int winUserId = thatUser.getUserId();
        int loseUserId = user.getUserId();
        userMapper.userWin(winUserId);
        userMapper.userLose(loseUserId);
        onlineUserManager.exitGameRoom(user.getUserId());
        roomManager.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
    }
}
